package com.qian.ddj.pay.util;

import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;

import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

/**
 */
public class RSAUtils {

    /**
     * 签名算法RSA
     */
    public static final String KEY_ALGORITHM = "RSA";

    /**
     * 签名算法SHA1WithRSA
     */
    public static final String SIGNATURE_ALGORITHM = "SHA1WithRSA";

    /**
     * 商户私钥
     */
    private static PrivateKey sysPrivateKey = null;

    /**
     * 商户公钥
     */
    private static PublicKey sysPublicKey = null;

    /**
     * 七分钱公钥
     */
    private static PublicKey sevenPubKey = null;


    static {

        try {
            // 商户私钥
            String privateKeyStr = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAPb0peTU+Qvkqyq7TuG4kt2tC8ysiYMk+8sTFc2pbw4OYu1/TngnMP3ONCdxHfinQSs5JAFhk9I3C5/+XJK/z2WuJvC7eD0263xzU4TpwOFnEPjJ5SRBhh4MqTH7Fz+W3KmgjufkCF/AVMcjV9OXk5zwbCgvo809vngPsKkI1pJjAgMBAAECgYAfDbqCoOlEPpfrgqwzpBMLvwPZ0+Ri0la7PYYjW2f0m4iDFtwWLc9ySuiyAP5k0xtVxRSq+8srxvI2RzT62xXIEzbjpp9yx4/qNdVaJMBhR2iHPL9nslZFTzLi3KDO5wv2pjYQ+mwvnVlsQMzZgVANOEOpTZ6AISXFiECG+fCnUQJBAPujYPMxZXwrPgz7x4AKi3V5+dv8vS+ZL1s65U8GikfLJ2HUcsBkdRHBFH5+lm/8khbH66q3wZxX9Fk6T9t3pAkCQQD7PH2v42TKqlHKqaA1mfEtlK1QrAf1oIaFMHrZPitzUxBL0LGTL8ww+7aNFM9+NfNDO4Bazht78Kq6h6Tdu9YLAkEAkZZj+DAjFCT8oIxnTzhKmWw52EIwvsI0+OZpV0BkbscmAN7miVNVvDDmh4z7wszxRMbkHYB1PtxQXfNz0nk06QJBAIzfompZy06IqkxFSPxFUaMJVxWBIQVt+X/9ayUdYyfLT7vzTV8G0iw1OGtrW92dSsZMOvCv2WFp1ZG6NYvPo3kCQQD3/0jsPsbP91jfgyyyLymW+2TZU4gIQLdlJVpWM/abUk6i3A6spxmb5KlXTLT29NmqLxbnBgG4wI0v3kG2VUTK";

            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

            // 因为java里面不识别x509格式的私钥，所以必须转换为 pkcs8格式方可使用
            // java异常描述为： java.security.spec.InvalidKeySpecException: Only RSAPrivate(Crt)KeySpec and PKCS8EncodedKeySpec supported for RSA private keys
            byte[] keyBytes = Base64.decode(privateKeyStr);
            PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
            sysPrivateKey = keyFactory.generatePrivate(pkcs8KeySpec);

            // 商户公钥
            String publicKeyStr = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD29KXk1PkL5Ksqu07huJLdrQvMrImDJPvLExXNqW8ODmLtf054JzD9zjQncR34p0ErOSQBYZPSNwuf/lySv89lribwu3g9Nut8c1OE6cDhZxD4yeUkQYYeDKkx+xc/ltypoI7n5AhfwFTHI1fTl5Oc8GwoL6PNPb54D7CpCNaSYwIDAQAB";

            byte[] pubkeyBytes = Base64.decode(publicKeyStr);
            X509EncodedKeySpec pubkeySpec = new X509EncodedKeySpec(pubkeyBytes);
            sysPublicKey = keyFactory.generatePublic(pubkeySpec);

            // 七分钱公钥
            String sevenPubKeyStr = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4G+OSs43I0Ctw7nxxuJPauTFsPyjMKkfsvYEcw4wqbn82KQWbFiSTy7P5hul4wdoZaFW5lSnHug+lyjn64t0dtCsaViOWefWrpL1gWZNpOc9gk6qNhQ0120ikHLE1SLH//gVStf+TDeVtaW+4Uzs5J7+/shdvfgU5T4+gxBk9jQIDAQAB";
            byte[] sevenPubKeyBytes = Base64.decode(sevenPubKeyStr);
            X509EncodedKeySpec sevenPubKeySpec = new X509EncodedKeySpec(sevenPubKeyBytes);
            sevenPubKey = keyFactory.generatePublic(sevenPubKeySpec);


        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public static PublicKey getSevenPayPubKey() {
        return sevenPubKey;
    }

    /**
     * <p>
     * 用私钥对信息生成数字签名
     * </p>
     *
     * @param data       已加密数据
     * @param privateKey 私钥(BASE64编码)
     * @return
     * @throws Exception
     */
    public static String sign(byte[] data, PrivateKey privateKey) throws Exception {

        if (null == privateKey) {
            privateKey = sysPrivateKey;
        }

        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initSign(privateKey);
        signature.update(data);
        return parseByte2HexStr(signature.sign());
    }

    /**
     * <p>
     * 校验数字签名
     * </p>
     *
     * @param data      已加密数据
     * @param publicKey 公钥(BASE64编码)
     * @param sign      数字签名
     * @return
     * @throws Exception
     */
    public static boolean verify(byte[] data, PublicKey publicKey, String sign)
            throws Exception {

        if (null == publicKey) {
            publicKey = sysPublicKey;
        }

        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initVerify(publicKey);
        signature.update(data);
        return signature.verify(parseHexStr2Byte(sign));
    }


    /**
     * 将二进制转换成16进制
     *
     * @param buf
     * @return
     */
    public static String parseByte2HexStr(byte buf[]) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < buf.length; i++) {
            String hex = Integer.toHexString(buf[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex.toUpperCase());
        }
        return sb.toString();
    }

    /**
     * 将16进制转换为二进制
     *
     * @param hexStr
     * @return
     */
    public static byte[] parseHexStr2Byte(String hexStr) {
        if (hexStr.length() < 1) {
            return null;
        }
        byte[] result = new byte[hexStr.length() / 2];
        for (int i = 0; i < hexStr.length() / 2; i++) {
            int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
            int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
            result[i] = (byte) (high * 16 + low);
        }
        return result;
    }

    public static void main(String[] args) throws Exception {
        RSAUtils.sign("你好".getBytes("UTF-8"), null);
    }
}  
